/**
 * 线性插值两个数字
 */
function lerp(a: number, b: number, t: number) {
  return a + (b - a) * t;
}

/**
 * #RRGGBB -> {r,g,b}
 */
function hexToRgb(hex: string) {
  const m = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)!;
  return {
    r: parseInt(m[1], 16),
    g: parseInt(m[2], 16),
    b: parseInt(m[3], 16),
  };
}

/**
 * {r,g,b} -> #RRGGBB
 */
function rgbToHex(r: number, g: number, b: number) {
  const toHex = (x: number) => Math.max(0, Math.min(255, Math.round(x))).toString(16).padStart(2, '0');
  return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}

/**
 * 在多段颜色停靠点之间线性插值，stops 按 0..1 递增
 */
function interpolateMultiStops(stops: string[], t: number) {
  const n = stops.length;
  if (n === 0) return '#808080';
  if (n === 1) return stops[0];

  const seg = 1 / (n - 1);
  const i = Math.max(0, Math.min(n - 2, Math.floor(t / seg)));
  const localT = (t - i * seg) / seg;

  const c1 = hexToRgb(stops[i]);
  const c2 = hexToRgb(stops[i + 1]);

  return rgbToHex(lerp(c1.r, c2.r, localT), lerp(c1.g, c2.g, localT), lerp(c1.b, c2.b, localT));
}

/**
 * 连续线性颜色映射：少→红 深，中间过渡 橙→青，多→蓝 深
 * 保持原函数签名，内部改为线性插值
 */
export function mapValueToColor(value: number, min: number, max: number): string {
  // 颜色停靠点（可按设计替换）：红 -> 橙 -> 青 -> 蓝
  const stops = ['#e74c3c', '#f39c12', '#1abc9c', '#3498db'];

  if (!Number.isFinite(value) || !Number.isFinite(min) || !Number.isFinite(max)) return '#808080';
  if (min === max) return stops[stops.length - 1];

  // 归一化并裁剪到 [0,1]
  const t = Math.max(0, Math.min(1, (value - min) / (max - min)));

  // t 越小越红越深，t 越大越蓝越深
  return interpolateMultiStops(stops, t);
}

/**
 * 以 0 为中心的发散映射：
 * <0: 橙→红；>0: 青→蓝；=0: 中性灰
 * maxPos: 当前时刻所有社区“正值”的最大值
 * maxNegAbs: 当前时刻所有社区“负值的绝对值”的最大值
 */
export function mapDivergingByZero(
  value: number,
  maxPos: number,
  maxNegAbs: number,
  opts?: {
    zeroColor?: string;
    posStops?: [string, string]; // 低→高
    negStops?: [string, string]; // 低→高（绝对值）
  }
): string {
  const zeroColor = opts?.zeroColor ?? '#d1d5db';          // 中性灰（有数据但=0）
  const posStops = opts?.posStops ?? ['#1abc9c', '#3498db']; // 青→蓝
  const negStops = opts?.negStops ?? ['#f39c12', '#e74c3c']; // 橙→红
  const EPS = 1e-9;

  // 无法计算时的兜底
  if (!Number.isFinite(value)) return '#808080';

  if (value > EPS) {
    const t = maxPos > 0 ? Math.min(1, value / maxPos) : 1;
    return interpolateMultiStops(posStops, t);
  } else if (value < -EPS) {
    const t = maxNegAbs > 0 ? Math.min(1, Math.abs(value) / maxNegAbs) : 1;
    return interpolateMultiStops(negStops, t);
  } else {
    return zeroColor;
  }
}